package cn.iocoder.yudao.module.reading.dal.mysql.assignment;

import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.reading.dal.dataobject.assignment.AssignmentCompletionDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

/**
 * 作业完成记录 Mapper
 *
 * @author 芋道源码
 */
@Mapper
public interface AssignmentCompletionMapper extends BaseMapperX<AssignmentCompletionDO> {

    /**
     * 根据作业ID查询完成记录
     *
     * @param assignmentId 作业ID
     * @return 完成记录列表
     */
    default List<AssignmentCompletionDO> selectByAssignmentId(Long assignmentId) {
        return selectList(new LambdaQueryWrapperX<AssignmentCompletionDO>()
                .eq(AssignmentCompletionDO::getAssignmentId, assignmentId)
                .orderByDesc(AssignmentCompletionDO::getCompletedAt)
                .orderByDesc(AssignmentCompletionDO::getCreateTime));
    }

    /**
     * 根据作业ID和用户ID查询完成记录
     *
     * @param assignmentId 作业ID
     * @param userId       用户ID
     * @return 完成记录列表
     */
    default List<AssignmentCompletionDO> selectByAssignmentIdAndUserId(Long assignmentId, Long userId) {
        return selectList(new LambdaQueryWrapperX<AssignmentCompletionDO>()
                .eq(AssignmentCompletionDO::getAssignmentId, assignmentId)
                .eq(AssignmentCompletionDO::getUserId, userId)
                .orderByAsc(AssignmentCompletionDO::getCreateTime));
    }

    /**
     * 根据作业ID、用户ID和绘本ID查询完成记录
     *
     * @param assignmentId 作业ID
     * @param userId       用户ID
     * @param bookId       绘本ID
     * @return 完成记录
     */
    default AssignmentCompletionDO selectByAssignmentIdAndUserIdAndBookId(Long assignmentId, Long userId, Long bookId) {
        return selectOne(new LambdaQueryWrapperX<AssignmentCompletionDO>()
                .eq(AssignmentCompletionDO::getAssignmentId, assignmentId)
                .eq(AssignmentCompletionDO::getUserId, userId)
                .eq(AssignmentCompletionDO::getBookId, bookId));
    }

    /**
     * 统计作业已完成人数（去重）
     * 只统计完成了该作业所有绘本的用户
     *
     * @param assignmentId 作业ID
     * @return 已完成人数
     */
    @Select("SELECT COUNT(DISTINCT user_id) FROM (" +
            "  SELECT user_id, COUNT(*) as completed_books " +
            "  FROM assignment_completions " +
            "  WHERE assignment_id = #{assignmentId} AND is_completed = 1 " +
            "  GROUP BY user_id " +
            "  HAVING completed_books = (" +
            "    SELECT total_books FROM class_assignments WHERE id = #{assignmentId}" +
            "  )" +
            ") t")
    Integer countCompletedByAssignmentId(Long assignmentId);

    /**
     * 根据作业ID查询已完成的用户ID列表（只包含完成所有绘本的用户）
     *
     * @param assignmentId 作业ID
     * @return 已完成用户ID列表
     */
    @Select("SELECT user_id FROM (" +
            "  SELECT user_id, COUNT(*) as completed_books " +
            "  FROM assignment_completions " +
            "  WHERE assignment_id = #{assignmentId} AND is_completed = 1 " +
            "  GROUP BY user_id " +
            "  HAVING completed_books = (" +
            "    SELECT total_books FROM class_assignments WHERE id = #{assignmentId}" +
            "  )" +
            ") t")
    List<Long> selectCompletedUserIdsByAssignmentId(Long assignmentId);

    /**
     * 根据用户ID查询完成记录
     *
     * @param userId 用户ID
     * @return 完成记录列表
     */
    default List<AssignmentCompletionDO> selectByUserId(Long userId) {
        return selectList(new LambdaQueryWrapperX<AssignmentCompletionDO>()
                .eq(AssignmentCompletionDO::getUserId, userId)
                .orderByDesc(AssignmentCompletionDO::getCompletedAt)
                .orderByDesc(AssignmentCompletionDO::getCreateTime));
    }

    /**
     * 根据作业ID删除所有完成记录
     *
     * @param assignmentId 作业ID
     * @return 删除的记录数
     */
    default int deleteByAssignmentId(Long assignmentId) {
        return delete(new LambdaQueryWrapperX<AssignmentCompletionDO>()
                .eq(AssignmentCompletionDO::getAssignmentId, assignmentId));
    }

}
